package com.linq.cool.system.controller;

import com.linq.cool.common.constants.Constants;
import com.linq.cool.common.constants.UserConstants;
import com.linq.cool.common.core.domain.BaseController;
import com.linq.cool.common.core.domain.Result;
import com.linq.cool.common.core.utils.SecurityUtils;
import com.linq.cool.common.core.utils.StringUtils;
import com.linq.cool.common.log.annotation.Log;
import com.linq.cool.common.log.enums.BusinessType;
import com.linq.cool.common.security.annotation.PreAuthorize;
import com.linq.cool.system.domain.SysMenu;
import com.linq.cool.system.dto.SysMenuQueryDTO;
import com.linq.cool.system.service.SysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: yqlin
 * @Date: 2021/1/20 02:36
 * @Description:
 * @Version: 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("menu")
public class SysMenuController extends BaseController {
    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public Result<?> getRouters() {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = sysMenuService.listMenuTreeByUserId(userId);
        return Result.ok(sysMenuService.buildMenus(menus));
    }

    /**
     * 获取菜单列表
     *
     * @param dto 菜单信息
     *
     * @return 结果
     */
    @PreAuthorize(hasPerm = "sys:menu:list")
    @GetMapping("list")
    public Result<?> list(SysMenuQueryDTO dto) {
        log.info("list--userId:{}", SecurityUtils.getUserId());
        return Result.ok(sysMenuService.listByUserId(dto, SecurityUtils.getUserId()));
    }

    /**
     * 根据菜单id获取详细信息
     *
     * @param menuId 菜单id
     *
     * @return 结果
     */
    @PreAuthorize(hasPerm = "sys:menu:query")
    @GetMapping(value = "{menuId}")
    public Result<?> getInfo(@PathVariable("menuId") Long menuId) {
        return Result.ok(sysMenuService.getById(menuId));
    }

    /**
     * 获取菜单下拉树列表
     *
     * @return 结果
     */
    @GetMapping("getTreeSelect")
    public Result<?> getTreeSelcet() {
        List<SysMenu> menus = sysMenuService.listByUserId(new SysMenuQueryDTO(), SecurityUtils.getUserId());
        return Result.ok(sysMenuService.buildMenuTreeSelect(menus));
    }

    /**
     * 加载对应角色菜单列表树
     *
     * @param roleId 角色id
     *
     * @return 结果
     */
    @GetMapping("getRoleMenuTreeSelect/{roleId}")
    public Result<?> getRoleMenuTreeSelect(@PathVariable("roleId") Long roleId) {
        List<SysMenu> menus = sysMenuService.listByUserId(new SysMenuQueryDTO(), SecurityUtils.getUserId());
        Map<String, Object> map = new HashMap<>(2);
        map.put("checkedKeys", sysMenuService.listByRoleId(roleId));
        map.put("menus", sysMenuService.buildMenuTreeSelect(menus));
        return Result.ok(map);
    }

    /**
     * 新增菜单
     *
     * @param menu 菜单信息
     *
     * @return 结果
     */
    @Log(moduleTitle = "菜单管理", businessType = BusinessType.INSERT)
    @PreAuthorize(hasPerm = "sys:menu:add")
    @PostMapping
    public Result<?> add(@Validated @RequestBody SysMenu menu) {
        if (sysMenuService.checkNameUnique(menu)) {
            return Result.fail("新增菜单'" + menu.getName() + "'失败，菜单名称已存在");
        }
        if (UserConstants.StateEnum.MENU_FRAME_OUTER.getCode().equals(menu.getIsFrame())
                && !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS)
        ) {
            return Result.fail("新增菜单'" + menu.getName() + "'失败，地址必须以http(s)://开头");
        }
        menu.setCreator(SecurityUtils.getUserId());
        return this.toResult(sysMenuService.save(menu));
    }

    /**
     * 修改菜单
     *
     * @param menu 菜单信息
     *
     * @return 结果
     */
    @Log(moduleTitle = "菜单管理", businessType = BusinessType.UPDATE)
    @PreAuthorize(hasPerm = "sys:menu:edit")
    @PutMapping
    public Result<?> edit(@Validated @RequestBody SysMenu menu) {
        if (sysMenuService.checkNameUnique(menu)) {
            return Result.fail("修改菜单'" + menu.getName() + "'失败，菜单名称已存在");
        }
        if (UserConstants.StateEnum.MENU_FRAME_OUTER.getCode().equals(menu.getIsFrame())
                && !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS)
        ) {
            return Result.fail("修改菜单'" + menu.getName() + "'失败，地址必须以http(s)://开头");
        }
        if (menu.getId().equals(menu.getParentId())) {
            return Result.fail("修改菜单'" + menu.getName() + "'失败，上级菜单不能选择自己");
        }
        menu.setGmtModified(new Date()).setModifier(SecurityUtils.getUserId());
        return this.toResult(sysMenuService.updateById(menu));
    }

    /**
     * 根据id删除菜单
     *
     * @param menuId 菜单id
     *
     * @return 结果
     */
    @Log(moduleTitle = "菜单管理", businessType = BusinessType.DELETE)
    @PreAuthorize(hasPerm = "sys:menu:remove")
    @DeleteMapping("{menuId}")
    public Result<?> remove(@PathVariable("menuId") Long menuId) {
        if (sysMenuService.hasChild(menuId)) {
            return Result.fail("存在子菜单,不允许删除");
        }
        if (sysMenuService.checkIsExistRole(menuId)) {
            return Result.fail("菜单已分配,不允许删除");
        }
        return this.toResult(sysMenuService.removeById(menuId));
    }
}

